﻿using System;
using System.Collections.Generic;
using System.Text;
using Model;
using GameHelp;
using System.Net.Sockets;
using System.Threading;
using Common;

namespace helper
{
    /// <summary>
    /// 当有信息产生时的委托
    /// </summary>
    /// <param name="character"></param>
    /// <param name="message"></param>
    public delegate void OnHaveMessageDelegate(Characters character, string message);

    /// <summary>
    /// 超时委托
    /// </summary>
    /// <param name="timeout"></param>
    public delegate void TimeoutDelegate(int timeout);

    public partial class AutoEngine
    {
        #region private data
        private TcpClient serverClient;
        private Account account;
        private List<ProcessDataAdapter> listenerList = new List<ProcessDataAdapter>();
        bool stopCurrent = false;//停止当前流程进行下一个流程
        bool stopAll = false;//停止所有流程
        bool paused = false;
        object pauseLocker = new object();//用于暂停的线程锁
        ManualResetEvent pauseEvent = new ManualResetEvent(true);
        int nextFightTime = 0;//下次战斗还需要等待的秒数
        GameState gameState = null;
        ProcessDataAdapter chatAdapter = new ProcessDataAdapter();//聊天数据适配器
        ProcessDataAdapter fightAdapter = new ProcessDataAdapter();//战斗数据适配器
        ProcessDataAdapter radio30CompleteAdapter = new ProcessDataAdapter();//30副本通关适配器
        ProcessDataAdapter radio50CompleteAdapter = new ProcessDataAdapter();//50副本通关适配器
        ProcessDataAdapter radio70CompleteAdapter = new ProcessDataAdapter();//70副本通关适配器

        /// <summary>
        /// 处理数据的委托
        /// </summary>
        /// <param name="datas">数据字节数组</param>
        /// <param name="length">数据长度</param>
        /// <returns>返回是否已经处理</returns>
        private delegate bool ProcessDataDelegate(byte[] datas, int length);

        /// <summary>
        /// 数据处理适配器
        /// </summary>
        class ProcessDataAdapter
        {
            protected bool enabled = false;
            protected int timeout = 0;
            protected DateTime startTime;
            protected Thread thread = null;
            protected ParameterizedThreadStart threadStart = null;


            /// <summary>
            /// 是否启用
            /// </summary>
            public bool Enabled
            {
                get { return enabled; }
                set
                {
                    enabled = value;
                    if (enabled&&timeout!=0)
                    {
                        startTime = DateTime.Now;
                        threadStart = new ParameterizedThreadStart(CheckTimeout);
                        thread.Start();
                    }
                }
            }
            /// <summary>
            /// 处理数据
            /// </summary>
            public ProcessDataDelegate ProcessData;

            /// <summary>
            /// 当监听超时时引发
            /// </summary>
            public event TimeoutDelegate OnTimeout;

            public ProcessDataAdapter()
            {
                this.timeout = 0;
            }

            public ProcessDataAdapter(int timeout)
            {
                this.timeout = timeout;
            }

            //超时后将适配器停止
            protected void CheckTimeout(object o)
            {
                if (timeout == 0)//不限制超时时间
                {
                    return;
                }
                while ((DateTime.Now - startTime).Seconds < timeout)
                {
                    Thread.Sleep(1000);
                }
                this.enabled = false;
                if (OnTimeout != null)
                {
                    OnTimeout(this.timeout);
                }
            }
        }
        #endregion

        /// <summary>
        /// 获取操作者的账户信息
        /// </summary>
        public Account Account
        {
            get { return account; }
        }

        /// <summary>
        /// 当有角色相关的信息时发生
        /// </summary>
        public event OnHaveMessageDelegate OnHaveMessage;

        /// <summary>
        /// 构造一个AutoEngine实例
        /// </summary>
        /// <param name="character">角色</param>
        /// <param name="serverClient">服务端连接</param>
        /// <param name="writeMethod">信息输出方法</param>
        public AutoEngine(Account account, TcpClient serverClient)
        {
            this.serverClient = serverClient;
            this.account = account;

            chatAdapter.ProcessData = new ProcessDataDelegate(ProcessChatData);//聊天数据
            chatAdapter.Enabled = true;
            listenerList.Add(chatAdapter);

            fightAdapter.ProcessData = new ProcessDataDelegate(ProcessFightData);//战斗数据
            fightAdapter.Enabled = true;
            listenerList.Add(fightAdapter);

            radio30CompleteAdapter.ProcessData = new ProcessDataDelegate(ProcessRadio30CompleteData);//30副本通关
            radio50CompleteAdapter.ProcessData = new ProcessDataDelegate(ProcessRadio50CompleteData);//50副本通关
            radio70CompleteAdapter.ProcessData = new ProcessDataDelegate(ProcessRadio70CompleteData);//70副本通关
        }

        /// <summary>
        /// 开始运行自动游戏引擎
        /// </summary>
        public void Start()
        {
            //开始按照配置文件进行自动游戏
            Thread thread = new Thread(new ParameterizedThreadStart(AutoGame));
            thread.Start();
        }

        /// <summary>
        /// 处理数据，当有数据需要处理时调用的方法
        /// </summary>
        /// <param name="datas"></param>
        /// <param name="length"></param>
        public void ProcessData(byte[] datas, int length)
        {
            foreach (ProcessDataAdapter listenter in listenerList)
            {
                if (listenter.Enabled)
                {
                    if (!listenter.ProcessData(datas, length))//处理数据，根据返回的状态决定是否继续调用下一个监听者
                    {
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// 自动游戏线程方法
        /// </summary>
        /// <param name="characterName"></param>
        private void AutoGame(object charObject)
        {
            GameConfig config = Manager.GetConfig(account);
            GameState state = Manager.GetState(account);

            if (config == null)//不存在配置文件
            {
                return;
            }
            Thread.Sleep(10000);//休息5秒钟等待客户端和服务端的数据通讯完毕
            AutoRadio30(config);//30副本
            AutoRadio50(config);//50副本
            AutoRadio70(config);//70副本
            AutoDailyQuest(config);//老板娘任务
        }

        private void AutoDailyQuest(GameConfig config)
        {
            throw new NotImplementedException();
        }

        private void AutoRadio70(GameConfig config)
        {
            throw new NotImplementedException();
        }

        private void AutoRadio50(GameConfig config)
        {
            throw new NotImplementedException();
        }

        private void AutoRadio30(GameConfig config)
        {
            if (!config.AutoRadio30)
            {
                MessageWrite("配置文件设置为：不自动进行30副本，已跳过。");
                return;
            }

            if (gameState.Radio30Date.ToShortDateString().Equals(DateTime.Now.ToShortDateString()))
            {
                if (gameState.Radio30Completed)
                {
                    MessageWrite("今天的30副本已完成。");
                    return;
                }
            }

            if (config.RadioQuestType == RadioQuest.Radio30)
            {
                MessageWrite("接受困难30副本任务。");
                QuestacceptRadio30();
            }

            if (config.Radio30Type == RadioType.Hard)
            {
                EnterRadio30(RadioType.Hard);
                MessageWrite( "进入30困难副本.");
            }
            else
            {
                EnterRadio30(RadioType.Easy);
                MessageWrite("进入30简单副本.");
            }

            gameState.Radio30Date = DateTime.Now;
            int count = 1;

            while (!gameState.Radio30Completed)
            {
                MessageWrite("进入30" + EnumConverter.GetString(config.Radio30Type) + "副本第" + count + "次战斗");
                fightAdapter.Enabled = true;//启动监听器
                FightRadio30(RadioType.Hard);

                if (nextFightTime > 0)//上次战斗还没结束
                {
                    Thread.Sleep(nextFightTime);
                    continue;
                }
                else
                {
                    Thread.Sleep(3000 + count * 1000);//战斗时间
                }
                FinshFight();//结束战斗

                if (this.stopCurrent)
                {
                    MessageWrite( "已停止自动30副本.");
                    this.stopCurrent = false;
                    return;
                }
                pauseEvent.WaitOne();//暂停
            }

            if (config.RadioQuestType == RadioQuest.Radio30)
            {
               FinshQuestRadio30();//提交副本任务
            }

            MessageWrite( "30副本已通关.");
        }

        /// <summary>
        /// 处理监听器接收到的聊天数据
        /// </summary>
        /// <param name="datas">数据</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据分发者是否应该将数据继续分发到下一个监听者</returns>
        private bool ProcessChatData(byte[] datas, int length)
        {
            if (datas.Length > 20)//聊天信息数据长度肯定大于20
            {
                //聊天信息
                if (datas[2] == 0xFF && datas[3] == 0xF0)
                {
                    string dataString = UTF8Encoding.UTF8.GetString(datas, 0, length);
                    int index = dataString.IndexOf(ChatFormat.colorStartTag);
                    if (index > -1)
                    {
                        Chat chat = new Chat();
                        chat.Character = new Characters();
                        chat.Character.Name = dataString.Substring(7, index - 13);//姓名
                        chat.Color = dataString.Substring(index + 3, 6);//说话的颜色
                        chat.Message = dataString.Substring(index + 10);
                        //对聊天信息进行处理，这里只是显示在信息框里。
                        if (OnHaveMessage != null)
                        {
                            OnHaveMessage(account.Character, "[" + chat.Character.Name + "]说：" + chat.Message);
                        }
                    }
                    else//可能是公告等信息，直接输出
                    {
                        if (OnHaveMessage != null)
                        {
                            OnHaveMessage(null, Tools.ConvertChar(dataString));
                        }
                    }

                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 处理发出战斗后的战斗返回数据
        /// </summary>
        /// <param name="datas">数据</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据分发者是否应该将数据继续分发到下一个适配器</returns>
        private bool ProcessFightData(byte[] datas, int length)
        {
            nextFightTime = GetNextFightTime(datas, length);//上次战斗仍未结束
            if (nextFightTime == -1)
            {
                return true;
            }
            else
            {
                if (OnHaveMessage != null)
                {
                    OnHaveMessage(account.Character, "还需要等待" + nextFightTime + "秒才能开始下一次战斗.");
                }
                fightAdapter.Enabled = false;//停止监听器
                return false;
            }
        }

        /// <summary>
        /// 检测30副本是否通关
        /// </summary>
        /// <param name="datas">数据</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据分发者是否应该将数据继续分发到下一个适配器</returns>
        private bool ProcessRadio30CompleteData(byte[] datas, int length)
        {
            if (FightRadio30Sucess(datas, length))//检测是否通关
            {
                radio30CompleteAdapter.Enabled = false;
                gameState.Radio30Completed = true;
                return false;
            }
            return true;
        }

        /// <summary>
        /// 检测50副本是否通关
        /// </summary>
        /// <param name="datas">数据</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据分发者是否应该将数据继续分发到下一个适配器</returns>
        private bool ProcessRadio50CompleteData(byte[] datas, int length)
        {
            if (FightRadio50Sucess( datas, length))//检测是否通关
            {
                radio50CompleteAdapter.Enabled = false;
                gameState.Radio50Completed = true;
                return false;
            }
            return true;
        }

        /// <summary>
        /// 检测70副本是否通关
        /// </summary>
        /// <param name="datas">数据</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据分发者是否应该将数据继续分发到下一个适配器</returns>
        private bool ProcessRadio70CompleteData(byte[] datas, int length)
        {
            if (FightRadio70Sucess( datas, length))//检测是否通关
            {
                radio70CompleteAdapter.Enabled = false;
                gameState.Radio70Completed = true;
                return false;
            }
            return true;
        }

        /// <summary>
        /// 输入信息
        /// </summary>
        /// <param name="message"></param>
        private void MessageWrite(string message)
        {
            if (OnHaveMessage != null)
            {
                OnHaveMessage(account.Character, message);
            }
        }
    }
}
